/*
 * $Id: time_conv.c,v 1.12 2006-02-07 07:42:54 bacon Exp $
 */
 
#include <xp/bas/time.h>
#include <xp/bas/locale.h>
#include <xp/bas/memory.h>
#include <xp/bas/string.h>
#include <xp/bas/mstring.h>
#include <time.h>

/* TODO: REVAMP ROUTINES HERE */
 
int xp_gmtime (xp_time_t t, xp_tm_t* ct)
{
	/* TODO: totally revamp this function */
	time_t tt = t / XP_MSEC_IN_SEC;

#ifdef _WIN32
	struct tm* tm = gmtime(&tt);
	if (tm == XP_NULL) return -1;
	xp_memcpy (ct, tm, xp_sizeof(xp_tm_t));
#else
	if (gmtime_r (&tt, ct) == XP_NULL) return -1;
#endif
	return 0;
}

int xp_localtime (xp_time_t t, xp_tm_t* ct)
{
	/* TODO: totally revamp this function */
	time_t tt = t / XP_MSEC_IN_SEC;
#ifdef _WIN32
	xp_tm_t* tm = localtime(&tt);
	if (tm == XP_NULL) return -1;
	xp_memcpy (ct, tm, xp_sizeof(xp_tm_t));
#else
	if (localtime_r (&tt, ct) == XP_NULL) return -1;
#endif
	return 0;
}

int xp_mktime (xp_tm_t* tm, xp_time_t* t)
{
	time_t x;
	x = mktime (tm);
	if (x == (time_t)-1) return -1;

	*t = x * XP_MSEC_IN_SEC;
	return 0;
}

xp_size_t xp_formattime (
	xp_char_t* buf, xp_size_t size, const xp_char_t* fmt, xp_tm_t* tm)
{
	/* TODO: totally revamp this function */
#ifdef XP_CHAR_IS_MCHAR
	return strftime (buf, size, fmt, tm);
#else
	xp_mchar_t mbuf[128 * 10];
	xp_mchar_t fbuf[128];
	xp_mchar_t* mp, * fp;
	xp_size_t msz, fsz, n, n2;

	fsz = xp_wcsmclen(fmt) + 1;
	if (fsz <= 1) return 0;

	if (size > xp_countof(mbuf)) {
		msz = size * 10;
		mp = (xp_mchar_t*)xp_malloc (msz);
		if (mp == XP_NULL) return 0;
	}
	else {
		mp = mbuf;
		msz = xp_countof(mbuf);
	}

	if (fsz > xp_countof(fbuf)) {
		fp = (xp_mchar_t*)xp_malloc (fsz);
		if (fp == XP_NULL) {
			if (size > xp_countof(mbuf)) xp_free (mp);
			return 0;
		}
	}
	else fp = fbuf;

	n = xp_wcstomcs (fmt, fp, fsz);
	if (n == (xp_size_t)-1 || n < xp_strlen(fmt)) {
		if (size > xp_countof(mbuf)) xp_free (mp);
		if (size > xp_countof(fbuf)) xp_free (fp);
		return 0;
	}

	n = strftime (mp, msz, fp, tm);
	if (n > 0) {
		n2 = xp_mcstowcs (mp, buf, size);
		n = (n2 == (xp_size_t)-1 || n2 < xp_mstrlen(mp))? 0: xp_strlen(buf);
	}

	if (size > xp_countof(mbuf)) xp_free (mp);
	if (size > xp_countof(fbuf)) xp_free (fp);

	return n;
#endif
}
